/*
 * TrainModel
 *
 * 2012-12-07 20:30
 *
 * Leon Lai
 *
 * Work history (not the same as commit messages):
 *   2012-12-07 18:30  --  2012-12-07 20:30
 *     Added class TrainModel & TrainModelJPanel.
 *     Added class and instance variables in TrainModel.
 *     Added ten public methods in TrainModel.
 *   2012-12-08 20:00  --  2012-12-08 23:00
 *     Added method sendBundle in TrainModel.
 *     Split int failureStatus into three boolean variables.
 *     Added method pullBrake in TrainModel.
 *     Added method releaseBrake in TrainModel.
 *     Added variable brakeOn in TrainModel.
 *     Added method update in TrainModel.
 *   2012-12-13 14:00  --  2012-12-13 18:00
 *     ...
 */

import java.util.*;
import java.util.Timer;

import javax.swing.*;
import javax.swing.event.*;

/**
 * @author Leon Lai
 */
public class TrainModel
{
	public static final long ONE_SECOND = 500; 
	public static Timer globalTimer = new Timer();

	static final String[] STATUS_MESSAGES = {"Train Model :  idle", "Train Model :  bundle from track model received", "Train Model :  bundle to train controller sent"};
	static byte status = 0;
	static Map<Integer, TrainModel> id2TrainModel = new HashMap<Integer, TrainModel>();
	static int idTotal = 0;

	int      id;
	TrainController associatedTrainController;
	double   length;
	double   height;
	double   width;
	double   mass;
	int      carCount;
	int      crewCount;
	int      passengerCount = 0;
	boolean  lightsOn  = false;
	boolean  doorsOpen = false;
	double   temperature;
	double[] powerLimits        = new double[2];  // {min, max}
	double[] accelerationLimits = new double[2];  // {min, max}
	double[] velocityLimits     = new double[2];  // {min, max}
	int      authority;
	int      authorityRemaining;
	double   power        = 0;
	double   acceleration = 0;
	double   velocity     = 0;
	double   positionOnCurrentTrackBlock = 0;
//	List        <Block> routeInformation;
//	ListIterator<Block> routeInformationIterator;
//	Block       currentTrackBlock;
	boolean  brakeOn            = false;
	boolean  emergencyBrakeOn   = false;
	boolean  failedTrainEngine  = false;
	boolean  failedSignalPickup = false;
	boolean  failedBrake        = false;

    static
    {
    	JFrame frame = new JFrame("Subsystem GUI - Train Model");
    	frame.setBounds(730, 165, 470, 150);
    	frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    	frame.getContentPane().add(new TrainModelJPanel());
    	frame.pack();
    	frame.setVisible(true);
    }

	public TrainModel()
	{
		this.id = idTotal++;
		id2TrainModel.put(id, this);
		associatedTrainController = new TrainController(this);
		this.length             = 0.0;
		this.height             = 0.0;
		this.width              = 0.0;
		this.mass               = 123000.0;
		this.carCount           = 8;
		this.crewCount          = 2;
		this.temperature        = 23.0;
		this.authority          = 8;
		this.authorityRemaining = this.authority;
//		List        <Block> routeInformation;
//		ListIterator<Block> routeInformationIterator = routeInformation.listIterator(0);
//		Block       currentTrackBlock = routeInformationIterator.hasNext() ? routeInformationIterator.next() : null;
		globalTimer.scheduleAtFixedRate(new TimerTask() {
			public void run()
			{
				TrainModel tm = TrainModel.id2TrainModel.get(id);
				tm.update();
				//tm.associatedTrainController.setPower();
			}
		}, 0, ONE_SECOND);
		//TrainModelJPanel.refresh();
	}

	/**
	 * Causes the train to go into train engine failure mode.
	 * <p>
	 * As one of the three vital failures, it will activate the brake to stop the train.
	 * <p>
	 * As a simple model, train engine failure is manually activated by a dedicated failure user.
	 */
	public void failTrainEngine()
	{
		failedTrainEngine = true;
		pullBrake();
		power = 0;
	}

	/**
	 * Causes the train to go into signal pickup failure mode.
	 * <p>
	 * As one of the three vital failures, it will cause the train engine to shut down and activate the brake to stop the train.
	 * <p>
	 * As a simple model, signal pickup failure is manually activated by a dedicated failure user.
	 */
	public void failSignalPickup()
	{
		failedSignalPickup = true;
		pullBrake();
		power = 0;
	}

	/**
	 * Causes the train to go into brake failure mode.
	 * <p>
	 * As one of the three vital failures, it will cause the train engine to shut down to stop the train.
	 * <p>
	 * As a simple model, brake failure is manually activated by a dedicated failure user.
	 */
	public void failBrake()
	{
		failedBrake = true;
		// Handle
		releaseBrake();
		power = 0;
	}

	/**
	 * Pulls the emergency brake of the train.
	 * <p>
	 * The train will decelerate at emergency brake deceleration rate until it has stopped.
	 * <p>
	 * A passenger or a crew member can pull the emergency brake via the associated train controller which will then call this method.
	 */
	public void pullEmergencyBrake()
	{
		emergencyBrakeOn = true;
	}

	/**
	 * Pulls the brake of the train.
	 * <p>
	 * If brake has failed, nothing changes.
	 * Otherwise, brake is activated.
	 * Then, unless the emergency brake is active, the train will decelerate at minimum acceleration (maximum deceleration) rate until brake is released.
	 * <p>
	 * The associated train controller calculates the necessity to pull the brake and calls this method.
	 */
	public void pullBrake()
	{
		if (failedBrake) return;
		brakeOn = true;
		if (emergencyBrakeOn) return;
		acceleration = accelerationLimits[0];
	}

	/**
	 * Releases the brake of the train.
	 * <p>
	 * The associated train controller calculates the necessity to release the brake and calls this method.
	 */
	public void releaseBrake()
	{
		brakeOn = false;
	}

	/**
	 * Changes the power of the train engine by setting it to a new value.
	 * <p>
	 * If train engine has failed, nothing changes.
	 * Otherwise, power is changed to the new value.
	 * Then, unless brake or emergency brake is pulled, acceleration changes.
	 * <p>
	 * The associated train controller calculates the power to be set as necessary and calls this method.
	 *
	 * @param  power The new power for the train engine
	 */
	public void setPower(double power)
	{
		if (failedTrainEngine) return;
		this.power = power;
		if (brakeOn || emergencyBrakeOn) return;
		acceleration = power / velocity / mass;
	}

	/**
	 * Updates the train velocity and position on current track block based on acceleration.
	 */
	private void update()
	{
		double grade, length;
		int type;
		boolean tunnel;
		double speedLimit;
		velocity += ONE_SECOND * acceleration;
		positionOnCurrentTrackBlock += ONE_SECOND * velocity;
		// if (positionOnCurrentTrackBlock >= 1) currentTrackBlock = routeInformationIterator.hasNext() ? routeInformationIterator.next() : null;
		// positionOnCurrentTrackBlock = 
		// currentTrackBlock.trainOnBlock(this);
		TrainModelJPanel.refresh();
	}

	/**
	 * Turns on the exterior lights of the train.
	 * <p>
	 * When inside the tunnel, the train shall have its exterior lights on.
	 * <p>
	 * The associated train controller calculates the necessity to turn on the lights and calls this method.
	 */
	public void turnLightsOn()
	{
		lightsOn = true;
	}

	/**
	 * Turns off the exterior lights of the train.
	 * <p>
	 * When not inside the tunnel, the train should have its exterior lights off.
	 * <p>
	 * The associated train controller calculates the necessity to turn off the lights and calls this method.
	 */
	public void turnLightsOff()
	{
		lightsOn = false;
	}

	/**
	 * Opens the doors of the train.
	 * <p>
	 * When at a station, the train shall have its doors open.
	 * <p>
	 * The associated train controller calculates the necessity to open the doors and calls this method.
	 */
	public void openDoors()
	{
		doorsOpen = true;
	}

	/**
	 * Closes the doors of the train.
	 * <p>
	 * When not at a station, the train shall have its doors closed.
	 * <p>
	 * The associated train controller calculates the necessity to close the doors and calls this method.
	 */
	public void closeDoors()
	{
		doorsOpen = false;
	}

	/**
	 * Adjusts the temperature value on the train AC by setting it to a new value.
	 * <p>
	 * As a simple model, the train interior temperature is equal to the temperature on its AC at any moment.
	 * <p>
	 * The associated train controller calculates the temperature to be set as desired and calls this method.
	 *
	 * @param temperature The new temperature for the train AC
	 */
	public void setTemperature(double temperature)
	{
		this.temperature = temperature;
	}

	/*
	 * Sends a TMBundle to the train model.
	 * <p>
	 * The train model will then construct a TNBundle and send it to the associated train controler
	 * Calling this method simulates a track circuit sending signals to a train.
	 * <p>
	 * The current track block calls this method to pass a TMBundle.
	 *
	 * @param tmbundle A TMBundle from the current track block
	 *
	public void receive(TMBundle tmbundle)
	{
		TNBundle tnbundle = new TNBundle(tmbundle);
		associatedTrainController.sendBundle(tnbundle);
	}*/

	public static void main(String[] arguments)
	{
		new TrainModel();
	}
}

/**
 * @author Leon Lai
 */
class TrainModelJPanel extends JPanel
{
	private static JLabel status                           = new JLabel();
	private static JLabel idLabel                          = new JLabel();
	private static JLabel lengthLabel                      = new JLabel();
	private static JLabel heightLabel                      = new JLabel();
	private static JLabel widthLabel                       = new JLabel();
	private static JLabel massLabel                        = new JLabel();
	private static JLabel carCountLabel                    = new JLabel();
	private static JLabel crewCountLabel                   = new JLabel();
	private static JLabel passengerCountLabel              = new JLabel();
	private static JLabel lightsOnLabel                    = new JLabel();
	private static JLabel doorsOpenLabel                   = new JLabel();
	private static JLabel temperatureLabel                 = new JLabel();
	private static JLabel powerLimitsLabel                 = new JLabel();
	private static JLabel accelerationLimitsLabel          = new JLabel();
	private static JLabel velocityLimitsLabel              = new JLabel();
	private static JLabel powerLabel                       = new JLabel();
	private static JLabel accelerationLabel                = new JLabel();
	private static JLabel velocityLabel                    = new JLabel();
	private static JLabel positionOnCurrentTrackBlockLabel = new JLabel();
	private static JLabel authorityLabel                   = new JLabel();
	private static JLabel authorityRemainingLabel          = new JLabel();
	private static JSpinner id                             = new JSpinner();
	private static JTextField length                       = new JTextField();
	private static JTextField height                       = new JTextField();
	private static JTextField width                        = new JTextField();
	private static JTextField mass                         = new JTextField();
	private static JTextField carCount                     = new JTextField();
	private static JTextField crewCount                    = new JTextField();
	private static JTextField passengerCount               = new JTextField();
	private static JTextField lightsOn                     = new JTextField();
	private static JTextField doorsOpen                    = new JTextField();
	private static JTextField temperature                  = new JTextField();
	private static JTextField powerLimits                  = new JTextField();
	private static JTextField accelerationLimits           = new JTextField();
	private static JTextField velocityLimits               = new JTextField();
	private static JTextField authority                    = new JTextField();
	private static JTextField authorityRemaining           = new JTextField();
	private static JTextField power                        = new JTextField();
	private static JTextField acceleration                 = new JTextField();
	private static JTextField velocity                     = new JTextField();
	private static JTextField positionOnCurrentTrackBlock  = new JTextField();
	private static JSeparator jSeparator1                  = new JSeparator();
	private static JSeparator jSeparator2                  = new JSeparator();

	public TrainModelJPanel()
	{
		status                          .setText("Bundle status:");
		idLabel                         .setText("Train ID");
		lengthLabel                     .setText("Length (m)");
		heightLabel                     .setText("Height (m)");
		widthLabel                      .setText("Width (m)");
		massLabel                       .setText("Mass (kg)");
		carCountLabel                   .setText("Number of cars");
		crewCountLabel                  .setText("Crew count");
		passengerCountLabel             .setText("Passenger count");
		lightsOnLabel                   .setText("Lights on ?");
		doorsOpenLabel                  .setText("Doors open ?");
		temperatureLabel                .setText("Temperature (C)");
		powerLimitsLabel                .setText("Power limits (W)");
		accelerationLimitsLabel         .setText("Acceleration limits (m/s^2)");
		velocityLimitsLabel             .setText("Velocity limits (m/s)");
		authorityLabel                  .setText("Authority (#)");
		authorityRemainingLabel         .setText("Authority remaining (#)");
		powerLabel                      .setText("Power (W)");
		accelerationLabel               .setText("Acceleration (m/s^2)");
		velocityLabel                   .setText("Velocity (m/s)");
		positionOnCurrentTrackBlockLabel.setText("Position on current track block");

		id.addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent evt) {
				refresh();
			}
		});

		GroupLayout layout = new GroupLayout(this);
		this.setLayout(layout);
		layout.setHorizontalGroup(
			layout.createParallelGroup(GroupLayout.Alignment.LEADING)
			.addGroup(layout.createSequentialGroup()
				.addContainerGap()
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
					.addGroup(layout.createSequentialGroup()
						.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
							.addComponent(idLabel)
							.addComponent(lengthLabel)
							.addComponent(heightLabel)
							.addComponent(widthLabel)
							.addComponent(massLabel)
							.addComponent(carCountLabel)
							.addComponent(crewCountLabel)
							.addComponent(passengerCountLabel)
							.addComponent(lightsOnLabel)
							.addComponent(doorsOpenLabel)
							.addComponent(temperatureLabel)
							.addComponent(powerLimitsLabel)
							.addComponent(accelerationLimitsLabel)
							.addComponent(velocityLimitsLabel)
							.addComponent(authorityLabel)
							.addComponent(authorityRemainingLabel)
							.addComponent(powerLabel)
							.addComponent(accelerationLabel)
							.addComponent(velocityLabel)
							.addComponent(positionOnCurrentTrackBlockLabel))
						.addGap(18, 18, 18)
						.addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
							.addComponent(id, GroupLayout.DEFAULT_SIZE, 218, Short.MAX_VALUE)
							.addComponent(length)
							.addComponent(height)
							.addComponent(width)
							.addComponent(mass)
							.addComponent(carCount)
							.addComponent(crewCount)
							.addComponent(passengerCount)
							.addComponent(lightsOn)
							.addComponent(doorsOpen)
							.addComponent(temperature)
							.addComponent(powerLimits)
							.addComponent(accelerationLimits)
							.addComponent(velocityLimits)
							.addComponent(authority)
							.addComponent(authorityRemaining)
							.addComponent(power)
							.addComponent(acceleration)
							.addComponent(velocity)
							.addComponent(positionOnCurrentTrackBlock)))
					.addComponent(status)
					.addComponent(jSeparator1)
					.addComponent(jSeparator2))
				.addContainerGap())
		);
		layout.setVerticalGroup(
			layout.createParallelGroup(GroupLayout.Alignment.LEADING)
			.addGroup(layout.createSequentialGroup()
				.addGap(11, 11, 11)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(status, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addComponent(jSeparator1, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE)
				.addGap(11, 11, 11)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(idLabel)
					.addComponent(id, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addComponent(jSeparator2, GroupLayout.PREFERRED_SIZE, 10, GroupLayout.PREFERRED_SIZE)
				.addGap(11, 11, 11)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(lengthLabel)
					.addComponent(length, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(heightLabel)
					.addComponent(height, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(widthLabel)
					.addComponent(width, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(massLabel)
					.addComponent(mass, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(carCountLabel)
					.addComponent(carCount, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(crewCountLabel)
					.addComponent(crewCount, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(passengerCountLabel)
					.addComponent(passengerCount, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(lightsOnLabel)
					.addComponent(lightsOn, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(doorsOpenLabel)
					.addComponent(doorsOpen, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(temperatureLabel)
					.addComponent(temperature, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(powerLimitsLabel)
					.addComponent(powerLimits, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(accelerationLimitsLabel)
					.addComponent(accelerationLimits, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(velocityLimitsLabel)
					.addComponent(velocityLimits, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(authorityLabel)
					.addComponent(authority, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(authorityRemainingLabel)
					.addComponent(authorityRemaining, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(powerLabel)
					.addComponent(power, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(accelerationLabel)
					.addComponent(acceleration, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(velocityLabel)
					.addComponent(velocity, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
				.addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
					.addComponent(positionOnCurrentTrackBlockLabel)
					.addComponent(positionOnCurrentTrackBlock, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
				.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
		);

		refresh();
	}

	static void refresh()
	{
		CTCGUI.trainID = (Integer)id.getValue();
		status.setText("");
		TrainModel thisTrainModel = TrainModel.id2TrainModel.get((Integer)id.getValue());
		if (thisTrainModel == null)
		{
			length                     .setText("N/A");
			height                     .setText("N/A");
			width                      .setText("N/A");
			mass                       .setText("N/A");
			carCount                   .setText("N/A");
			crewCount                  .setText("N/A");
			passengerCount             .setText("N/A");
			lightsOn                   .setText("N/A");
			doorsOpen                  .setText("N/A");
			temperature                .setText("N/A");
			powerLimits                .setText("N/A");
			accelerationLimits         .setText("N/A");
			velocityLimits             .setText("N/A");
			authority                  .setText("N/A");
			authorityRemaining         .setText("N/A");
			power                      .setText("N/A");
			acceleration               .setText("N/A");
			velocity                   .setText("N/A");
			positionOnCurrentTrackBlock.setText("N/A");
		}
		else
		{
			length                     .setText("" + thisTrainModel.length);
			height                     .setText("" + thisTrainModel.height);
			width                      .setText("" + thisTrainModel.width);
			mass                       .setText("" + thisTrainModel.mass);
			carCount                   .setText("" + thisTrainModel.carCount);
			crewCount                  .setText("" + thisTrainModel.crewCount);
			passengerCount             .setText("" + thisTrainModel.passengerCount);
			lightsOn                   .setText("" + thisTrainModel.lightsOn);
			doorsOpen                  .setText("" + thisTrainModel.doorsOpen);
			temperature                .setText("" + thisTrainModel.temperature);
			powerLimits                .setText("min=" + thisTrainModel.powerLimits[0]        + "; max=" + thisTrainModel.powerLimits[1]);
			accelerationLimits         .setText("min=" + thisTrainModel.accelerationLimits[0] + "; max=" + thisTrainModel.accelerationLimits[1]);
			velocityLimits             .setText("min=" + thisTrainModel.velocityLimits[0]     + "; max=" + thisTrainModel.velocityLimits[1]);
			authority                  .setText("" + thisTrainModel.authority);
			authorityRemaining         .setText("" + thisTrainModel.authorityRemaining);
			power                      .setText("" + thisTrainModel.power);
			acceleration               .setText("" + thisTrainModel.acceleration);
			velocity                   .setText("" + thisTrainModel.velocity);
			positionOnCurrentTrackBlock.setText("" + thisTrainModel.positionOnCurrentTrackBlock);
		}
	}		
}
